/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * htap_statistics.h
 * HTAP statistics provider.
 *
 * IDENTIFICATION
 * src/include/storage/htap/htap_statistics.h
 *
 * -------------------------------------------------------------------------
 */

#ifndef HTAP_STATISTICS_H
#define HTAP_STATISTICS_H

#include "iconfig_change_listener.h"
#include "numeric_statistic_variable.h"
#include "statistics_provider.h"
#include "typed_statistics_generator.h"
#include "htap_global.h"

namespace htap {
class DeltaThreadStatistics : public MOT::ThreadStatistics {
public:
    explicit DeltaThreadStatistics(uint64_t threadId, void *inplaceBuffer = nullptr);

    virtual ~DeltaThreadStatistics() {}

    /** Updates the memory statistics for absent updates. */
    inline void AddAbsentUpdate()
    {
        m_absentUpdate.AddSample(1);
    }

    /** Updates the memory statistics for present updates. */
    inline void AddPresentUpdate()
    {
        m_presentUpdate.AddSample(1);
    }

    /** Updates the memory statistics for absent deleted. */
    inline void AddAbsentDelete()
    {
        m_absentDelete.AddSample(1);
    }

    /** Updates the memory statistics for present deleted. */
    inline void AddPresentDelete()
    {
        m_presentDelete.AddSample(1);
    }

private:
    // number of absent/preset update/delete
    MOT::NumericStatisticVariable m_absentUpdate;
    MOT::NumericStatisticVariable m_presentUpdate;
    MOT::NumericStatisticVariable m_absentDelete;
    MOT::NumericStatisticVariable m_presentDelete;
};

class DeltaStatisticsProvider : public MOT::StatisticsProvider, public MOT::IConfigChangeListener {
public:

    /** Creates singleton instance. Must be called once during startup. */
    static bool CreateInstance();

    /** Destroys singleton instance. Must be called once during shutdown. */
    static void DestroyInstance();

    /** Get singleton instance. */
    static DeltaStatisticsProvider &GetInstance();

    /** Updates the memory statistics for absent updates. */
    inline void AddAbsentUpdate()
    {
        DeltaThreadStatistics *dts = GetCurrentThreadStatistics<DeltaThreadStatistics>();
        if (dts) {
            dts->AddAbsentUpdate();
        }
    }

    /** Updates the memory statistics for present updates. */
    inline void AddPresentUpdate()
    {
        DeltaThreadStatistics *dts = GetCurrentThreadStatistics<DeltaThreadStatistics>();
        if (dts) {
            dts->AddPresentUpdate();
        }
    }

    /** Updates the memory statistics for absent deleted. */
    inline void AddAbsentDelete()
    {
        DeltaThreadStatistics *dts = GetCurrentThreadStatistics<DeltaThreadStatistics>();
        if (dts) {
            dts->AddAbsentDelete();
        }
    }

    /** Updates the memory statistics for present deleted. */
    inline void AddPresentDelete()
    {
        DeltaThreadStatistics *dts = GetCurrentThreadStatistics<DeltaThreadStatistics>();
        if (dts) {
            dts->AddPresentDelete();
        }
    }

    /* *
     * @brief Derives classes should react to a notification that configuration changed. New
     * configuration is accessible via the ConfigManager.
     */
    void OnConfigChange() override;

protected:
    /* *
     * @brief Print current memory status summary.
     */
    void PrintStatisticsEx() override;

private:
    DeltaStatisticsProvider();
    ~DeltaStatisticsProvider() override;

    /** Registers the provider in the manager. */
    void RegisterProvider();

    /** @var The single instance. */
    static DeltaStatisticsProvider *m_provider;

    static MOT::TypedStatisticsGenerator<DeltaThreadStatistics, MOT::EmptyGlobalStatistics> m_generator;
};

class FlushThreadStatistics : public MOT::ThreadStatistics {
public:
    explicit FlushThreadStatistics(uint64_t threadId, void *inplaceBuffer = nullptr);

    virtual ~FlushThreadStatistics() {}

    inline void AddToNewRows(uint64_t value)
    {
        m_addingNewRows.AddSample(value);
    }
    inline void AddDeleteRows(uint64_t value)
    {
        m_deleteRows.AddSample(value);
    }
    inline void AddNumRG(uint64_t value)
    {
        m_numRG.AddSample(value);
    }
    inline void AddHandleDeleteCalls(uint64_t value)
    {
        m_numDeleteCall.AddSample(value);
    }

    /** Updates the memory statistics for insert-row modify time. */
    inline void AddPermanentFlushTime(int64_t micros)
    {
        m_permanentFlushTime.AddSample(micros);
    }

private:
    // total time spent in one permanent Flush loop
    MOT::NumericStatisticVariable m_permanentFlushTime;
    MOT::NumericStatisticVariable m_addingNewRows;
    MOT::NumericStatisticVariable m_deleteRows;
    MOT::NumericStatisticVariable m_numRG;
    MOT::NumericStatisticVariable m_numDeleteCall;
};

class FlushStatisticsProvider : public MOT::StatisticsProvider, public MOT::IConfigChangeListener {
public:

    /** Creates singleton instance. Must be called once during startup. */
    static bool CreateInstance();

    /** Destroys singleton instance. Must be called once during shutdown. */
    static void DestroyInstance();

    /** Get singleton instance. */
    static FlushStatisticsProvider &GetInstance();

    /** Updates Adding to new RG. */
    inline void AddToNewRows(uint64_t value)
    {
        FlushThreadStatistics *fts = GetCurrentThreadStatistics<FlushThreadStatistics>();
        if (fts) {
            fts->AddToNewRows(value);
        }
    }

    /** Updates Adding to full RG. */
    inline void AddDeleteRows(uint64_t value)
    {
        FlushThreadStatistics *fts = GetCurrentThreadStatistics<FlushThreadStatistics>();
        if (fts) {
            fts->AddDeleteRows(value);
        }
    }

    /** Updates Adding to full RG. */
    inline void AddHandleDeleteCalls(uint64_t value)
    {
        FlushThreadStatistics *fts = GetCurrentThreadStatistics<FlushThreadStatistics>();
        if (fts) {
            fts->AddHandleDeleteCalls(value);
        }
    }

    /** Updates Adding to full RG. */
    inline void AddNewRG(uint64_t value)
    {
        FlushThreadStatistics *fts = GetCurrentThreadStatistics<FlushThreadStatistics>();
        if (fts) {
            fts->AddNumRG(value);
        }
    }

    /** Updates the memory statistics for insert-row modify time. */
    inline void AddPermanentFlushTime(int64_t micros)
    {
        FlushThreadStatistics *mts = GetCurrentThreadStatistics<FlushThreadStatistics>();
        if (mts) {
            mts->AddPermanentFlushTime(micros);
        }
    }

    /* *
     * @brief Derives classes should react to a notification that configuration changed. New
     * configuration is accessible via the ConfigManager.
     */
    void OnConfigChange() override;

protected:
    /* *
     * @brief Print current memory status summary.
     */
    void PrintStatisticsEx() override;

private:
    FlushStatisticsProvider();
    ~FlushStatisticsProvider() override;

    /** Registers the provider in the manager. */
    void RegisterProvider();

    /** @var The single instance. */
    static FlushStatisticsProvider *m_provider;

    static MOT::TypedStatisticsGenerator<FlushThreadStatistics, MOT::EmptyGlobalStatistics> m_generator;
};

class ModifyThreadStatistics : public MOT::ThreadStatistics {
public:
    explicit ModifyThreadStatistics(uint64_t threadId, void *inplaceBuffer = nullptr);

    virtual ~ModifyThreadStatistics() {}

    /** Updates the memory statistics for insert-row modify time. */
    inline void AddInsertRowModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_insertRowModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyInsertRowModifyTime.AddSample(micros);
        } else {
            m_errorInsertRowModifyTime.AddSample(micros);
        }
    }

    /** Updates the memory statistics for update-row modify time. */
    inline void AddUpdateRowModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_updateRowModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyUpdateRowModifyTime.AddSample(micros);
        } else {
            m_errorUpdateRowModifyTime.AddSample(micros);
        }
    }

    /** Updates the memory statistics for delete-row modify time. */
    inline void AddDeleteRowModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_deleteRowModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyDeleteRowModifyTime.AddSample(micros);
        } else {
            m_errorDeleteRowModifyTime.AddSample(micros);
        }
    }

    /** Updates the memory statistics for commit-txn modify time. */
    inline void AddCommitTxnModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_commitTxnModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyCommitTxnModifyTime.AddSample(micros);
        } else {
            m_errorCommitTxnModifyTime.AddSample(micros);
        }
    }

    /** Updates the memory statistics for abort-txn modify time. */
    inline void AddAbortTxnModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_abortTxnModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyAbortTxnModifyTime.AddSample(micros);
        } else {
            m_errorAbortTxnModifyTime.AddSample(micros);
        }
    }

    /** Updates the memory statistics for commit-sub-txn modify time. */
    inline void AddCommitSubTxnModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_commitSubTxnModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyCommitSubTxnModifyTime.AddSample(micros);
        } else {
            m_errorCommitSubTxnModifyTime.AddSample(micros);
        }
    }

    /** Updates the memory statistics for abort-sub-txn modify time. */
    inline void AddAbortSubTxnModifyTime(int64_t micros, RC rc)
    {
        if (rc == HTAP_RC_OK) {
            m_abortSubTxnModifyTime.AddSample(micros);
        } else if (rc == HTAP_RC_EVENT_DISCARDED) {
            m_emptyAbortSubTxnModifyTime.AddSample(micros);
        } else {
            m_errorAbortSubTxnModifyTime.AddSample(micros);
        }
    }

private:
    // total time spent in insert/update/delete
    MOT::NumericStatisticVariable m_insertRowModifyTime;
    MOT::NumericStatisticVariable m_updateRowModifyTime;
    MOT::NumericStatisticVariable m_deleteRowModifyTime;
    MOT::NumericStatisticVariable m_commitTxnModifyTime;
    MOT::NumericStatisticVariable m_abortTxnModifyTime;
    MOT::NumericStatisticVariable m_commitSubTxnModifyTime;
    MOT::NumericStatisticVariable m_abortSubTxnModifyTime;
    MOT::NumericStatisticVariable m_emptyInsertRowModifyTime;
    MOT::NumericStatisticVariable m_emptyUpdateRowModifyTime;
    MOT::NumericStatisticVariable m_emptyDeleteRowModifyTime;
    MOT::NumericStatisticVariable m_emptyCommitTxnModifyTime;
    MOT::NumericStatisticVariable m_emptyAbortTxnModifyTime;
    MOT::NumericStatisticVariable m_emptyCommitSubTxnModifyTime;
    MOT::NumericStatisticVariable m_emptyAbortSubTxnModifyTime;
    MOT::NumericStatisticVariable m_errorInsertRowModifyTime;
    MOT::NumericStatisticVariable m_errorUpdateRowModifyTime;
    MOT::NumericStatisticVariable m_errorDeleteRowModifyTime;
    MOT::NumericStatisticVariable m_errorCommitTxnModifyTime;
    MOT::NumericStatisticVariable m_errorAbortTxnModifyTime;
    MOT::NumericStatisticVariable m_errorCommitSubTxnModifyTime;
    MOT::NumericStatisticVariable m_errorAbortSubTxnModifyTime;
};

class ModifyStatisticsProvider : public MOT::StatisticsProvider, public MOT::IConfigChangeListener {
public:

    /** Creates singleton instance. Must be called once during startup. */
    static bool CreateInstance();

    /** Destroys singleton instance. Must be called once during shutdown. */
    static void DestroyInstance();

    /** Get singleton instance. */
    static ModifyStatisticsProvider &GetInstance();

    /** Updates the memory statistics for insert-row modify time. */
    inline void AddInsertRowModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddInsertRowModifyTime(micros, rc);
        }
    }

    /** Updates the memory statistics for update-row modify time. */
    inline void AddUpdateRowModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddUpdateRowModifyTime(micros, rc);
        }
    }

    /** Updates the memory statistics for delete-row modify time. */
    inline void AddDeleteRowModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddDeleteRowModifyTime(micros, rc);
        }
    }

    /** Updates the memory statistics for commit-txn modify time. */
    inline void AddCommitTxnModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddCommitTxnModifyTime(micros, rc);
        }
    }

    /** Updates the memory statistics for abort-txn modify time. */
    inline void AddAbortTxnModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddAbortTxnModifyTime(micros, rc);
        }
    }

    /** Updates the memory statistics for commit-sub-txn modify time. */
    inline void AddCommitSubTxnModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddCommitSubTxnModifyTime(micros, rc);
        }
    }

    /** Updates the memory statistics for abort-sub-txn modify time. */
    inline void AddAbortSubTxnModifyTime(int64_t micros, RC rc)
    {
        ModifyThreadStatistics *mts = GetCurrentThreadStatistics<ModifyThreadStatistics>();
        if (mts) {
            mts->AddAbortSubTxnModifyTime(micros, rc);
        }
    }

    /* *
     * @brief Derives classes should react to a notification that configuration changed. New
     * configuration is accessible via the ConfigManager.
     */
    void OnConfigChange() override;

protected:
    /* *
     * @brief Print current memory status summary.
     */
    void PrintStatisticsEx() override;

private:
    ModifyStatisticsProvider();
    ~ModifyStatisticsProvider() override;

    /** Registers the provider in the manager. */
    void RegisterProvider();

    /** @var The single instance. */
    static ModifyStatisticsProvider *m_provider;

    static MOT::TypedStatisticsGenerator<ModifyThreadStatistics, MOT::EmptyGlobalStatistics> m_generator;
};
} // namespace htap

#endif /* HTAP_STATISTICS_H */
